﻿#include "tcpclienttest.h"

#include <QDateTime>
#include <QTextCodec>
#include <QThread>
#include <QtCore/QMetaEnum>

#include <net/netwriting.h>
QNET_USING_NAMESPACE

TcpClientTest::TcpClientTest(QObject *parent) : QObject(parent)
{
    m_session = Q_NULLPTR;
    m_client = Q_NULLPTR;
    m_thread = new QThread;
    m_timerID = 0;
    m_counter = 0;
    m_timerID = startTimer(5000);
    m_isAutoConnect = false;
    QObject::connect(this, &TcpClientTest::stop_signal,
                     this, &TcpClientTest::stop_slot);
    QObject::connect(m_thread, &QThread::finished, this, &QObject::deleteLater);
    m_stopped = false;
}

TcpClientTest::~TcpClientTest()
{
    m_stopped = true;
    m_thread->deleteLater();
    if(m_client)
    {
        m_client->deleteLater();
    }
    m_session = Q_NULLPTR;
}

bool TcpClientTest::bind(QHostAddress localAddress, quint16 localPort)
{
    if(m_client)
    {
        return false;
    }
    m_client = new TcpClient(this);
    bool ok = m_client->bind(localAddress, localPort);
    if(!ok)
    {
        m_client->deleteLater();
        m_client = Q_NULLPTR;
    }
    return ok;
}

void TcpClientTest::setAutoConnect(bool isAuto)
{
    m_isAutoConnect = isAuto;
    if(m_client)
    {
        m_client->setAutoReconnect(m_isAutoConnect);
    }
}

void TcpClientTest::connect(QHostAddress remoteAddress, quint16 remotePort)
{
    if(!m_client)
    {
        bool ok = bind(QHostAddress::Any, 0);
        Q_ASSERT(ok);
    }
    m_client->setAutoReconnect(m_isAutoConnect);
    m_client->connect(remoteAddress, remotePort);

    if(!m_thread->isRunning())
    {
        m_thread->start();
    }
    this->moveToThread(m_thread);
}

void TcpClientTest::stop()
{
    if(!m_stopped)
    {
        m_stopped = true;
        setAutoConnect(false);
        emit stop_signal();
        m_thread->exit();
        m_thread->wait();
    }
}

void TcpClientTest::onStateChanged(TcpSession *session, bool connected)
{
    QString msg = QString(tr("会话%1:%2")).arg(session->remoteIp().toString())
            .arg(session->remotePort());
    if(connected)
    {
        m_session = session;
        m_session->setReading(this);

         msg.append(tr(" 已连接"));
    }else
    {
        msg.append(tr(" 已断开"));
        m_session = Q_NULLPTR;
    }
    emit log_signal(msg);
}

void TcpClientTest::onError(QAbstractSocket::SocketError error)
{
    QString msg;
    QTextStream stream(&msg);
    QMetaEnum metaEnum = QMetaEnum::fromType<QAbstractSocket::SocketError>();
    //枚举值转字符串
    stream << tr("检测到socket错误信息：") << metaEnum.valueToKey(error);
    emit log_signal(msg);
}

void TcpClientTest::fulfil(QSharedPointer<NetWriting> sender, int size)
{
    int packSize = sender.data()->size();
    m_counter.fetchAndAddAcquire(-packSize);

    QString msg ;
    if(size>0){
        msg = QString(tr("写入数据成功:%1")).arg(packSize);
    }else {
        msg = QString(tr("写入数据成功:%1")).arg(packSize);
    }
    msg.append(QString(tr("剩余数据:%1")).arg(m_counter));
    emit log_signal(msg);
}

void TcpClientTest::stop_slot()
{
    if(m_client)
    {
        m_client->deleteLater();
        m_client = Q_NULLPTR;

    }
    if(m_session)
    {
        m_session->setReading(Q_NULLPTR);
    }
    m_session = Q_NULLPTR;
}

void TcpClientTest::onProc(const QByteArray &arry)
{
    QString msg  = QString(tr("接收到数据:"));
    msg.append(arry);
    emit log_signal(msg);
}

void TcpClientTest::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == m_timerID)
    {
        if(m_session != Q_NULLPTR)
        {
            QByteArray arry = QDateTime::currentDateTime().toString().toUtf8();
            int writeSize = arry.size();
            QSharedPointer<NetWriting> writing(new NetWriting(arry), &QObject::deleteLater);
            static int id = -1;
            if(id == -1)
            {
                id = qRegisterMetaType<QSharedPointer<NetWriting>>("QSharedPointer<NetWriting>");
            }
            QObject::connect(writing.data(), &NetWriting::fulfil, this, &TcpClientTest::fulfil);
            m_counter.fetchAndAddAcquire(writeSize);

            if(!m_session->write(writing))
            {
                m_counter.fetchAndAddAcquire(-writeSize);
                QString msg ;
                QTextStream stream;
                stream.setString(&msg);
                stream << tr(" 向会话写入数据失败！") ;
                emit log_signal(msg);
            }
        }
    }
}
